﻿#region File Header
//============================================================================
//  FileName    :	SecurityUtility.cs
//
//  Description :	
//
//  Copyright (C) 2008, GrapeCity Inc.  All rights reserved.
//============================================================================
//
//----------------------------------------------------------------------------
//  Update Log:
//
//  Status                Date                      Name               BUG-ID
//----------------------------------------------------------------------------
// Created         2008/12/18 9:13:38     	    TonyGong		 	None
//----------------------------------------------------------------------------
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;
using System.IO;
using System.Globalization;

namespace SPMS.Utility
{
    /// <summary>
    /// 加密辅助类
    /// </summary>
    /// <remarks>提供了常用加解密算法的简单封装</remarks>
    /// <history>
    /// [zanezeng]               2009/9/15 11:43    修订
    /// [TonyGong]               2008/12/18 9:16    创建
    /// </history>
    public sealed class CryptographyUtility
    {
        #region ---Public Method

        /// <summary>
        /// 使用给定的哈希算法计算给定文件内容的哈希值
        /// </summary>
        /// <param name="fileName">要计算文件内容哈希的文件名</param>
        /// <param name="algorithm">用于计算文件内容哈希的哈希算法</param>
        /// <returns>表示文件内容哈希值字符串。字符串内容为哈希值的16进制表示。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="fileName"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用。</exception>
        /// <exception cref="FileNotFoundException">给定名称的文件没有找到</exception>
        /// <exception cref="IOException">读取文件内容的过程中发生的异常</exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/5 13:05    创建
        /// </history>
        public static string ComputeFileHash( string fileName, HashAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( fileName, "fileName" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            //判断给定的文件是否存在
            if (!File.Exists( fileName ))
            {
                //如果给定的文件不存在，则抛出异常
                throw new FileNotFoundException( string.Format( Properties.Resources.MSG_FILE_NOTFOUNT, fileName ), fileName );
            }

            //用于保存加密结果
            Byte[] result = null;

            //打开文件流
            using (FileStream stream = new FileStream( fileName, FileMode.Open, FileAccess.Read, FileShare.Read ))
            {
                //计算哈希值
                result = algorithm.ComputeHash( stream );
            }

            //返回加密结果的字符串表示
            return StringUtility.JoinObjects( result, string.Empty, true, string.Empty, string.Empty, "X2", CultureInfo.InvariantCulture );
        }

        /// <summary>
        /// 使用给定的哈希算法计算给定字符串内容的哈希值
        /// </summary>
        /// <param name="soruce">要计算哈希值的字符串</param>
        /// <param name="algorithm">用于计算文件内容哈希值的哈希算法</param>
        /// <returns>表示文件内容哈希值的长度为32的字符串</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="soruce"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用。</exception>
        /// <exception cref="FileNotFoundException">给定名称的文件没有找到</exception>
        /// <exception cref="IOException">读取文件内容的过程中发生的异常</exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/5 13:05    创建
        /// </history>
        public static string ComputeStringHash( string soruce, HashAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( soruce, "fileName" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            //计算哈希值
            byte[] result = algorithm.ComputeHash( Encoding.UTF8.GetBytes( soruce ) );

            //返回加密结果的字符串表示
            return StringUtility.JoinObjects( result, string.Empty, true, string.Empty, string.Empty, "X2", CultureInfo.InvariantCulture );
        }

        /// <summary>
        /// 验证给定文件的文件内容的哈希值是否与给定的哈希值相等
        /// </summary>
        /// <param name="fileName">要计算文件内容哈希值的文件名</param>
        /// <param name="hashValue">用于比较的哈希值，内容为哈希值的16制表示字符串。</param>
        /// <param name="algorithm">用于计算字符串内容哈希值的哈希算法</param>
        /// <returns>
        /// 如果文件内容的哈希值与给定的哈希值相等，则返回<c>true</c>；否则返回<c>false</c>。
        /// </returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="fileName"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用。</exception>
        /// <exception cref="FileNotFoundException">给定名称的文件没有找到</exception>
        /// <exception cref="IOException">读取文件内容的过程中发生的异常</exception>
        /// <history>
        /// [zanezeng]               2010/1/5 13:08    创建
        /// </history>
        public static bool VerifyFileHash( string fileName, string hashValue, HashAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( fileName, "fileName" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            //判断用于比较的哈希值是否为空引用或者为空字符串
            if (string.IsNullOrEmpty( hashValue ))
            {
                //如果用于比较的哈希值为空引用或者为空字符串，则总是返回不匹配
                return false;
            }

            //计算源哈希值
            string sourceHashValue = ComputeFileHash( fileName, algorithm );

            //比较哈希值
            return 0 == string.Compare( sourceHashValue, hashValue, StringComparison.InvariantCultureIgnoreCase );
        }

        /// <summary>
        /// 验证给定字符串内容的哈希值是否与给定的哈希值相等
        /// </summary>
        /// <param name="source">要计算哈希值的字符串</param>
        /// <param name="hashValue">用于比较的哈希值，内容为哈希值的16制表示字符串。</param>
        /// <param name="algorithm">用于计算字符串内容哈希值的哈希算法</param>
        /// <returns>
        /// 如果文件内容的哈希值与给定的哈希值相等，则返回<c>true</c>；否则返回<c>false</c>。如果<paramref name="hashValue"/>为空引用或者空字符串，则总是返回<c>false</c>。
        /// </returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="fileName"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用。</exception>
        /// <exception cref="FileNotFoundException">给定名称的文件没有找到</exception>
        /// <exception cref="IOException">读取文件内容的过程中发生的异常</exception>
        /// <history>
        /// [zanezeng]               2010/1/5 13:08    创建
        /// </history>
        public static bool VerifyStringHash( string source, string hashValue, HashAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( source, "source" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            //判断用于比较的哈希值是否为空引用或者为空字符串
            if (string.IsNullOrEmpty( hashValue ))
            {
                //如果用于比较的哈希值为空引用或者为空字符串，则总是返回不匹配
                return false;
            }

            //计算源哈希值
            string sourceHashValue = ComputeStringHash( source, algorithm );

            //比较哈希值
            return 0 == string.Compare( sourceHashValue, hashValue, StringComparison.InvariantCultureIgnoreCase );
        }

        /// <summary>
        /// 使用MD5哈希算法计算给定文件的文件内容的哈希值
        /// </summary>
        /// <param name="fileName">要计算内容哈希的文件名</param>
        /// <returns>表示文件内容哈希值字符串。字符串内容为哈希值的16进制表示。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="fileName"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <exception cref="FileNotFoundException">给定名称的文件没有找到</exception>
        /// <exception cref="IOException">读取文件内容的过程中发生的异常</exception>
        /// <history>
        /// [ZengE]      2010/1/5 11:59     修订
        /// [TonyGong]   2008/12/18 9:16    创建
        /// </history>
        public static string GetFileMD5Hash( string fileName )
        {
            //计算文件内容的MD5哈希值
            return ComputeFileHash( fileName, MD5.Create() );
        }

        /// <summary>
        /// 使用MD5哈希算法计算给定字符串的哈希值
        /// </summary>
        /// <param name="source">用于计算哈希的字符串</param>
        /// <returns>表示文件内容哈希值的长度为32的字符串</returns>
        /// <exception cref="ArgumentNullException">传入的引用参数为<c>null</c>引用。</exception>
        /// <history>
        /// [TonyGong]   2008/12/18 9:19    Created
        /// </history>
        public static string GetMD5Hash( string source )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( source, "source" );

            //计算给定字符串的MD5哈希值
            return ComputeStringHash( source, MD5.Create() );
        }

        /// <summary>
        /// 使用MD5哈希算法计算给定字符串的哈希值并且将计算出来的哈希值与给定的哈希值进行比较
        /// </summary>
        /// <param name="source">要计算哈希值的字符串.</param>
        /// <param name="hashValue">用于比较的以16值表示的哈希值字符串</param>
        /// <returns>
        /// 	如果匹配的返回<c>true</c>；否则返回<c>false</c>。如果<paramref name="hashValue"/>为空引用或者空字符串，则总是返回<c>false</c>。
        /// </returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="source"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [TonyGong]   2008/12/18 9:21    Created
        /// </history>
        public static bool VerifyMd5Hash( string source, string hashValue )
        {
            //断言参数异常
            ArgumentAssert.AssertArgumentNotNull( source, "source" );

            //判断用于比较的哈希值是否为空引用或者为空字符串
            if (string.IsNullOrEmpty( hashValue ))
            {
                //如果用于比较的哈希值为空引用或者为空字符串，则总是返回不匹配
                return false;
            }

            //验证哈希
            return VerifyStringHash( source, hashValue, MD5.Create() );
        }

        /// <summary>
        /// 使用SHA512哈希算法计算给定字符串的哈希值
        /// </summary>
        /// <param name="source">用于计算哈希值得字符串</param>
        /// <returns>表示文件内容哈希值字符串。字符串内容为哈希值的16进制表示。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="source"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [TonyGong]   2008/12/18 10:27    Created
        /// </history>
        public static string GetSHA512Hash( string source )
        {
            //断言参数异常
            ArgumentAssert.AssertArgumentNotNull( source, "source" );

            //计算哈希
            return ComputeStringHash( source, SHA512.Create() );
        }

        /// <summary>
        /// 使用SHA512哈希算法计算给定字符串的哈希值并且将计算出来的哈希值与给定的哈希值进行比较
        /// </summary>
        /// <param name="source">要计算哈希值的字符串.</param>
        /// <param name="hashValue">用于比较的以16值表示的哈希值字符串</param>
        /// <returns>
        /// 	如果匹配的返回<c>true</c>；否则返回<c>false</c>。如果<paramref name="hashValue"/>为空引用或者空字符串，则总是返回<c>false</c>。
        /// </returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="source"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [TonyGong]   2008/12/18 9:21    Created
        /// </history>
        public static bool VerifySHA512Hash( string source, string hashValue )
        {
            //断言参数异常
            ArgumentAssert.AssertArgumentNotNull( source, "source" );

            //判断用于比较的哈希值是否为空引用或者为空字符串
            if (string.IsNullOrEmpty( hashValue ))
            {
                //如果用于比较的哈希值为空引用或者为空字符串，则总是返回不匹配
                return false;
            }

            //验证哈希
            return VerifyStringHash( source, hashValue, SHA512.Create() );
        }

        /// <summary>
        /// 使用给定的算法签名给定的XML文件
        /// </summary>
        /// <param name="soruceFileName">要被签名的文件名称</param>
        /// <param name="signedFileName">用于保存签名文件的文件名称</param>
        /// <param name="algorithm">用于签名的算法对象</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="soruceFileName"/>为<c>null</c>引用或者为空字符串</exception>
        /// <exception cref="ArgumentNullException"><paramref name="signedFileName"/>为<c>null</c>引用或者为空字符串</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用。</exception>
        /// <exception cref="FileNotFoundException">给定名称的文件没有找到</exception>
        /// <exception cref="IOException">读取文件内容的过程中发生的异常</exception>
        /// <history>
        /// [TonyGong]   平成 21/2/10 10:12    Created
        /// </history>
        public static void Sign( string soruceFileName, string signedFileName, AsymmetricAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( soruceFileName, "soruceFileName" );
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( signedFileName, "signedFileName" );

            //创建XML文档对象
            XmlDocument document = new XmlDocument();

            //加载XML文件
            document.Load( soruceFileName );

            //签名XML文档
            Sign( document, algorithm );

            //保存签名的文档
            document.Save( signedFileName );
        }

        /// <summary>
        /// 使用给定的算法签名给定的<see cref="System.Xml.XmlDocument"/>对象
        /// </summary>
        /// <param name="document">需要被签名的<see cref="System.Xml.XmlDocument"/>对象</param>
        /// <param name="algorithm">用于签名的算法对象</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="document"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentException"><paramref name="document"/>为空文档。</exception>
        /// <history>
        /// [TonyGong]   平成 21/2/10 10:12    Created
        /// </history>
        public static void Sign( XmlDocument document, AsymmetricAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( document, "document" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            //判断文档是否为一个空文档
            if (null == document.DocumentElement)
            {
                //如果是一个空文档，则抛出异常
                throw new ArgumentException( Properties.Resources.MSG_SIGNATURE_EMPTYDOCUMENT, "document" );
            }

            //创建XML签名包装对象
            SignedXml signedXml = new SignedXml( document );

            //设置签名算法
            signedXml.SigningKey = algorithm;

            //创建表示XML签名的reference元素
            Reference reference = new Reference( "" );

            //创建由W3C定义的 XML 数字签名封装签名转换
            XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform();

            //添加签名转换
            reference.AddTransform( transform );

            //将前面引用元素添加到XML签名包装对象
            signedXml.AddReference( reference );

            //计算元素的签名
            signedXml.ComputeSignature();

            //获得元素的签名
            XmlElement elementSignature = signedXml.GetXml();

            //将元素的签名导入到元素所在的文档对象
            XmlNode signatureNode = document.ImportNode( elementSignature, true );

            //将元素的签名添加到元素所在的文档对象
            document.DocumentElement.AppendChild( signatureNode );
        }

        /// <summary>
        /// 使用给定的算法签名给定的<see cref="System.Xml.XmlElement"/>对象
        /// </summary>
        /// <param name="element">需要签名的<see cref="System.Xml.XmlElement"/>对象</param>
        /// <param name="algorithm">用于签名的算法对象</param>
        /// <remarks>如果要签名的元素没有指定id属性，则自动为要签名的元素指定一个唯一的id值</remarks>
        /// <exception cref="ArgumentNullException"><paramref name="element"/>为<c>null</c>引用</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用</exception>
        /// <exception cref="ArgumentException"><paramref name="element"/>的根元素为<c>null</c>引用，即不属于一个文档对象</exception>
        /// <history>
        /// [TonyGong]   平成 21/2/10 10:12    Created
        /// </history>
        public static void Sign( XmlElement element, AsymmetricAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( element, "element" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            //判断要签名的元素是否有根元素
            if (null == element.OwnerDocument.DocumentElement)
            {
                //抛出异常
                throw new ArgumentException( Properties.Resources.MSG_SIGNATURE_ROOTISMISSING, "element" );
            }

            //创建XML签名包装对象
            SignedXml signedXml = new SignedXml( element );

            //设置签名算法
            signedXml.SigningKey = algorithm;

            //创建表示XML签名的reference元素
            Reference reference = new Reference();

            //判断元素是否指定了ID属性
            if (!element.HasAttribute( "id" ))
            {
                //如果没有指定ID属性，则自动生成ID属性
                element.SetAttribute( "id", Guid.NewGuid().ToString( "B" ) );
            }

            //将引用设置为签名元素的ID
            reference.Uri = string.Format( "#{0}", element.Attributes["id"].Value );

            //创建由W3C定义的 XML 数字签名封装签名转换
            XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform();

            //添加签名转换
            reference.AddTransform( transform );

            //将前面引用元素添加到XML签名包装对象
            signedXml.AddReference( reference );

            //计算元素的签名
            signedXml.ComputeSignature();

            //获得元素的签名
            XmlElement elementSignature = signedXml.GetXml();

            //将元素的签名导入到元素所在的文档对象
            XmlNode signatureNode = element.OwnerDocument.ImportNode( elementSignature, true );

            //将元素的签名添加到元素所在的文档对象
            element.OwnerDocument.DocumentElement.AppendChild( signatureNode );
        }

        /// <summary>
        /// 判断给定的Xml文件的签名是否能够通过给定的算法的验证
        /// </summary>
        /// <param name="fileName">要进行签名验证的XML文件</param>
        /// <param name="algorithm">签名算法</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="fileName"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用</exception>
        /// <exception cref="FileNotFoundException">给定名称的文件没有找到</exception>
        /// <exception cref="IOException">读取文件内容的过程中发生的异常</exception>
        /// <history>
        /// [zanezeng]               2009/9/15 14:17    创建
        /// </history>
        public static bool VerifySignature( string fileName, AsymmetricAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( fileName, "fileName" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            //创建XML文档对象
            XmlDocument document = new XmlDocument();

            //加载XML文件
            document.Load( fileName );

            //验证签名
            return VerifySignature( document, algorithm );
        }

        /// <summary>
        /// 判断给定的<see cref="System.Xml.XmlElement"/>对象的签名是否能够通过给定的算法的验证
        /// </summary>
        /// <param name="document">要进行签名验证的<see cref="System.Xml.XmlElement"/>对象</param>
        /// <param name="algorithm">签名算法</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="document"/>为<c>null</c>引用</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用</exception>
        /// <history>
        /// [zanezeng]               2009/9/15 14:17    创建
        /// </history>
        public static bool VerifySignature( XmlDocument document, AsymmetricAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( document, "document" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            try
            {
                //获得所有的签名节点
                XmlNodeList nodes = document.GetElementsByTagName( "Signature" );

                //判断是否存在验证节点
                if (0 == nodes.Count)
                {
                    //如果不存在验证节点，则认为不能通过验证
                    return false;
                }

                //创建XML签名包装对象
                SignedXml signedXml = new SignedXml( document );

                //循环验证签名
                foreach (XmlElement element in nodes)
                {
                    //加载需要验证的签名
                    signedXml.LoadXml( element );

                    //检查签名
                    if (!signedXml.CheckSignature( algorithm ))
                    {
                        //如果签名检查失败，则返回False
                        return false;
                    }
                }

                //默认通过签名检查
                return true;
            }
            catch
            {
                //不抛出异常，总是返回验证失败
                return false;
            }
        }

        /// <summary>
        /// 验证给定<see cref="XmlDocument"/>的数字签名
        /// </summary>
        /// <param name="document">要验证签名的<see cref="XmlDocument"/>对象。</param>
        /// <param name="algorithm">用于验证签名的非对称算法对象</param>
        /// <returns>
        /// 	如果给定的<paramref name="document"/>通过数字签名验证，则返回<c>true</c>；否则返回<c>false</c>。
        /// </returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="document"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="algorithm"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [TonyGong]   平成 21/2/10 10:12    Created
        /// </history>
        public static bool VerifyXml( XmlDocument document, AsymmetricAlgorithm algorithm )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( document, "document" );
            ArgumentAssert.AssertArgumentNotNull( algorithm, "algorithm" );

            try
            {
                //创建签名验证的包装类
                SignedXml wrapper = new SignedXml( document );

                //在文档中检索签名节点
                XmlNodeList signatureNode = document.GetElementsByTagName( "Signature" );

                //判断签名节点有且只有一个
                if (signatureNode.Count != 1)
                {
                    //如果签名节点不存在，或者多于一个，则返回签名失败
                    return false;
                }

                //加载签名节点
                wrapper.LoadXml( (XmlElement)signatureNode[0] );

                //执行签名验证操作
                return wrapper.CheckSignature( algorithm );
            }
            catch
            {
                //不抛出异常，总是返回验证失败
                return false;
            }
        }

        /// <summary>
        /// 算法加密给定的字符串
        /// </summary>
        /// <param name="source">以UTF8编码的要加密的字符串</param>
        /// <returns>使用Base64编码的加密后的字符串。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="source"/>为<c>null</c>引用或者空字符串。</exception>
        /// <exception cref="CryptographicException">加密过程中发生的异常。</exception>
        /// <history>
        /// [zanezeng]               2010/1/11 16:26    创建
        /// </history>
        public static string EncryptString( string source )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( source, "source" );

            //创建DES算法提供者
            DESCryptoServiceProvider provider = new DESCryptoServiceProvider();

            //创建加密转换运算对象
            ICryptoTransform transform = provider.CreateEncryptor( DEFAULT_KEY, DEFAULT_IV );

            //获得加密的源数据
            byte[] data = Encoding.UTF8.GetBytes( source );

            //获得加密的结果
            byte[] result = transform.TransformFinalBlock( data, 0, data.Length );

            //返回结果的Base64编码
            return Convert.ToBase64String( result );
        }

        /// <summary>
        /// 使用DES算法加密给定的字符串
        /// </summary>
        /// <param name="source">要加密的以UTF8编码的字符串</param>
        /// <returns>使用Base64编码的加密后的字符串。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="source"/>为<c>null</c>引用或者空字符串。</exception>
        /// <exception cref="CryptographicException">加密过程中发生的异常。</exception>
        /// <history>
        /// [CaiShengRong]   2009/3/24 10:22    Created
        /// </history>
        public static string EncryptStringEx( string source )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( source, "source" );

            //创建DES算法提供者
            DESCryptoServiceProvider provider = new DESCryptoServiceProvider();

            //读取密钥设定
            Guid settings = new Guid( Properties.Resources.VALUE_DEFAULT_KEY );

            //用于保存候选数据
            byte[] candidate = settings.ToByteArray();

            //生成密钥
            byte[] key = GenerateArray( candidate, provider.LegalKeySizes[0].MaxSize / 8, 2 );

            //生成向量
            byte[] iv = GenerateArray( candidate, provider.LegalBlockSizes[0].MaxSize / 8, 6 );

            //创建加密转换运算对象
            ICryptoTransform transform = provider.CreateEncryptor( key, iv );

            //获得加密的源数据
            byte[] data = Encoding.UTF8.GetBytes( source );

            //获得加密的结果
            byte[] result = transform.TransformFinalBlock( data, 0, data.Length );

            //返回结果的Base64编码
            return Convert.ToBase64String( result );
        }

        /// <summary>
        /// 使用DES算法解密给定的以UTF8编码的内容为Base64编码的字符串
        /// </summary>
        /// <param name="source">要解密的以Base64编码的字符串</param>
        /// <returns>解密后的以UTF8编码的字符串。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="source"/>为<c>null</c>引用或者空字符串。</exception>
        /// <exception cref="FormatException"><paramref name="source"/>不是合法的Base64编码的字符串。</exception>
        /// <exception cref="CryptographicException">解密过程中发生的异常。</exception>
        /// <history>
        /// [CaiShengRong]   2009/3/24 10:23    Created  您的潜力，俺的动力
        /// </history>
        public static string DecryptStringEx( string source )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( source, "source" );

            //获得要解密的数据
            byte[] data = Convert.FromBase64String( source );

            //创建DES算法提供者
            DESCryptoServiceProvider provider = new DESCryptoServiceProvider();

            //读取密钥设定
            Guid settings = new Guid( Properties.Resources.VALUE_DEFAULT_KEY );

            //用于保存候选数据
            byte[] candidate = settings.ToByteArray();

            //生成密钥
            byte[] key = GenerateArray( candidate, provider.LegalKeySizes[0].MaxSize / 8, 2 );

            //生成向量
            byte[] iv = GenerateArray( candidate, provider.LegalBlockSizes[0].MaxSize / 8, 6 );

            //创建加密转换运算对象
            ICryptoTransform transform = provider.CreateDecryptor( key, iv );

            //获得解密的结果
            byte[] result = transform.TransformFinalBlock( data, 0, data.Length );

            //返回解密结果
            return Encoding.UTF8.GetString( result );
        }

        /// <summary>
        /// 使用DES算法解密给定的以UTF8编码的内容为Base64编码的字符串
        /// </summary>
        /// <param name="source">要解密的以Base64编码的字符串</param>
        /// <returns>解密后的以UTF8编码的字符串。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="source"/>为<c>null</c>引用或者空字符串。</exception>
        /// <exception cref="FormatException"><paramref name="source"/>不是合法的Base64编码的字符串。</exception>
        /// <exception cref="CryptographicException">解密过程中发生的异常。</exception>
        /// <history>
        /// [CaiShengRong]   2009/3/24 10:23    Created  您的潜力，俺的动力
        /// </history>
        public static string DecryptString( string source )
        {
            //断言参数

            // 避免在x64下运行导致不抛出异常的程序崩溃，增加对空字符串的检查
            // 20100422 Valentine
            //ArgumentAssert.AssertArgumentNotNull( source, "source" );
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty(source, "source");
            // END

            //获得要解密的数据
            byte[] data = Convert.FromBase64String( source );

            //创建DES算法提供者
            DESCryptoServiceProvider provider = new DESCryptoServiceProvider();

            //创建加密转换运算对象
            ICryptoTransform transform = provider.CreateDecryptor( DEFAULT_KEY, DEFAULT_IV );

            //获得解密的结果
            byte[] result = transform.TransformFinalBlock( data, 0, data.Length );

            //返回解密结果
            return Encoding.UTF8.GetString( result );
        }

        #endregion

        #region ---Private Method

        /// <summary>
        /// 从给定的Byte数组中生成一个数组
        /// </summary>
        /// <param name="source">用于生成数组的源数组</param>
        /// <param name="length">生成数组的长度</param>
        /// <param name="offset">偏移值</param>
        /// <returns>生成的数组</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="source"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentException"><paramref name="source"/>为空数组。</exception>
        /// <exception cref="ArgumentException"><paramref name="length"/>小于等于0。</exception>
        /// <history>
        /// [zanezeng]               2010/1/5 15:04    创建
        /// </history>
        private static byte[] GenerateArray( byte[] source, int length, int offset )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( source, "source" );
            ArgumentAssert.AssertCollectionArgumentNotNullOrEmpty<byte>( source, "source" );
            ArgumentAssert.AssertArgumentRange( length, 1, int.MaxValue, "length" );

            //用于保存生成的数组
            List<byte> result = new List<byte>();

            //用于保存元素值
            byte element;

            //循环生成数组的各个元素
            for (int i = 0; i < length; i++)
            {
                //获得给定位置的元素之
                element = source[(i + offset) % source.Length];

                //转换一次
                element = source[element % source.Length];

                //添加元素之
                result.Add( element );
            }

            //返回结果
            return result.ToArray();
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 加密密钥
        /// </summary>
        private static readonly byte[] DEFAULT_KEY = System.Text.Encoding.UTF8.GetBytes( "12345678" );

        /// <summary>
        /// 加密的向量
        /// </summary>
        private static readonly byte[] DEFAULT_IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };

        #endregion
    }
}